﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;
using System.Linq;
using Xceed.Silverlight.Data;

namespace Xceed.Silverlight.DataGrid
{
  internal class StubDataItem : DataItem
  {
    internal StubDataItem( SourcePosition relativeSourcePosition, long offset )
      : base()
    {
      if( relativeSourcePosition == null )
        throw new ArgumentNullException( "relativeSourcePosition" );

      m_relativeSourcePosition = relativeSourcePosition;
      m_offset = offset;
      m_hashCode = this.GenerateHashCode();
    }

    public SourcePosition RelativeSourcePosition { get { return m_relativeSourcePosition; } }

    public long Offset { get { return m_offset; } }


    private int GenerateHashCode()
    {
      SourcePosition position = m_relativeSourcePosition;
      int intOffset = ( int )Math.Max( ( long )int.MinValue, Math.Min( m_offset, ( long )int.MaxValue ) );
      if(position.IsOutOfBound)
      {
        return position.GetHashCode() ^ intOffset;
      }

      ItemPosition itemPosition = position as ItemPosition;
      if( itemPosition != null )
      {
        return ( itemPosition.Item != null )
          ? itemPosition.Item.GetHashCode() ^ intOffset
          : intOffset;
      }

      SortPosition sortPosition = position as SortPosition;
      if( sortPosition != null )
      {
        int hash = intOffset;
        foreach( object value in sortPosition.SortValues )
        {
          hash ^= ( value == null ) ? 0 : value.GetHashCode();
        }
        return hash;
      }

      //All the SourcePosition types are handled here...
      throw new DataGridInternalException();
    }

    public override int GetHashCode()
    {
      return m_hashCode;
    }

    public override bool Equals( object obj )
    {
      StubDataItem that = obj as StubDataItem;

      if( that == null )
        return false;

      if( object.ReferenceEquals( this, that ) )
        return true;

      if( this.m_hashCode != that.m_hashCode )
        return false;

      if( this.m_offset != that.m_offset )
        return false;

      if(object.ReferenceEquals( this.m_relativeSourcePosition, that.m_relativeSourcePosition))
        return true;

      //If any of them were out of bound (BeforeFirst, AfterLast) the only equality possible would 
      //have been detected by the previous "if" (ReferenceEqual)
      if( this.m_relativeSourcePosition.IsOutOfBound || this.m_relativeSourcePosition.IsOutOfBound )
        return false;

      ItemPosition thisItem = this.m_relativeSourcePosition as ItemPosition;
      ItemPosition thatItem = that.m_relativeSourcePosition as ItemPosition;

      //Only one of them is an ItemPosition. Not equals.
      if((thisItem != null) != (thatItem != null))
        return false;

      //If this is true, the other is not an Item either (see previous "if")
      if(thisItem != null)
        return object.Equals(thisItem.Item, thatItem.Item);

      //Here they are obviously SortPositions (only type left)
      SortPosition thisSort = (SortPosition)this.m_relativeSourcePosition;
      SortPosition thatSort = (SortPosition)that.m_relativeSourcePosition;

      if(thisSort.StartPosition != thatSort.StartPosition)
        return false;

      //Ok, compare the sort values...
      return thisSort.SortValues.SequenceEqual(thatSort.SortValues);
    }

    private int m_hashCode;
    private long m_offset;
    private SourcePosition m_relativeSourcePosition;
  }
}
